/**
 * 
 */
package com.hm.uums.interceptor;

import java.math.BigInteger;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.hm.common.Constant;
import com.hm.common.annotation.Function;
import com.hm.common.enums.Authority;
import com.hm.common.exception.NoAuthException;
import com.hm.common.utils.StringUtils;
import com.hm.uums.service.UserService;

/**
 * @author hwg
 *
 *         2021年3月2日
 */
public class AccessInterceptor implements HandlerInterceptor {
	Logger logger = LoggerFactory.getLogger(AccessInterceptor.class);

	@Autowired
	private UserService userService;

	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		if (!(handler instanceof HandlerMethod)) {
			return true;
		}
		
		if (!((HandlerMethod) handler).hasMethodAnnotation(Function.class)) {
			return true;
		}

		Function function = ((HandlerMethod) handler).getMethodAnnotation(Function.class);
		response.addHeader(Constant.REQUEST_FUNCTION_CODE, function.code());
		response.addHeader(Constant.REQUEST_FUNCTION_DESC, StringUtils.encodeUrl(function.description()));

		if (hasPermission(request, function)) {
			return true;
		}

		String reqId = request.getHeader(Constant.REQUEST_ID);
		throw new NoAuthException("Request id:" + reqId + ", Request uri:" + request.getRequestURI() + ", function code:" + function.code());
	}

	private boolean hasPermission(HttpServletRequest request, Function function) {
		if (function.authority() == Authority.UNREQUIRE_LOGIN) {//方法需要登录
			return true;
		}
		BigInteger userId = getUserId(request);
		if (function.authority() == Authority.REQUIRE_LOGIN) {//方法只需要登录
			return StringUtils.isNotEmpty(userId);
		}
		Set<String> funcSet = userService.getFunctionCodeByUser(userId);
		String authorityCode = function.code().toString().toLowerCase();
		return StringUtils.isNotEmpty(userId) && funcSet.contains(authorityCode);//方法需要登录，并且需要权限
	}

	private BigInteger getUserId(HttpServletRequest request) {
		return new BigInteger(request.getHeader(Constant.USER_ID));
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
	}

	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {

	}
}
